package com.yushu.common.config.datasource;


import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

/**
多数据源切面
 * @author test
 * @CreateDate 2020-12-03 15:47:25
 */
@Aspect
@Component
@EnableAspectJAutoProxy(proxyTargetClass = true)
/**
 * @EnableAspectJAutoProxy：
 *
 * 表示开启AOP代理自动配置，如果配@EnableAspectJAutoProxy表示使用cglib进行代理对象的生成；设置@EnableAspectJAutoProxy(exposeProxy=true)表示通过aop框架暴露该代理对象，aopContext能够访问.
 * 从@EnableAspectJAutoProxy的定义可以看得出，它引入AspectJAutoProxyRegister.class对象，该对象是基于注解@EnableAspectJAutoProxy注册一个AnnotationAwareAspectJAutoProxyCreator，该对象通过调用AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);注册一个aop代理对象生成器。
 */
public class DynamicDataSourceAspect {

    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    /**
     * 定义切点,
     * service包 以及其子包下 第一个参数为String 的方法作为切点
     */
    @Pointcut("execution( * com.yushu.*.service..*.*(String, ..))")
    public void serviceAspect() {
    }

    /**
     * 选择数据源
     *
     * @param point
     */
    @Before("serviceAspect()")
    public void switchDataSource(JoinPoint point) {

        Object[] params = point.getArgs();
        String param = (String) params[0];

        //        //获得访问的方法名
        String methodName = point.getSignature().getName();
//        //得到方法的参数的类型
        Class[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes();

        if (StringUtils.isBlank(param)) {
            return;
        }
        //如果参数不为空，并且数据源中包含当前值
        if (DynamicRoutingDataSource.isExistDataSource(param) && !param.equals(DynamicDataSourceContextHolder.getDataSourceKey())) {
            DynamicDataSourceContextHolder.setDataSourceKey(param);
        }

        logger.info("Switch DataSource to [{}] in Method [{}]", DynamicDataSourceContextHolder.getDataSourceKey(), point.getSignature());
    }

    /**
     * 重置数据源
     *
     * @param point
     */
    @After("serviceAspect()")
    public void restoreDataSource(JoinPoint point) {
        DynamicDataSourceContextHolder.clearDataSourceKey();
        logger.info("Restore DataSource to [{}] in Method [{}]",DynamicDataSourceContextHolder.getDataSourceKey(), point.getSignature());
    }

}
